import { BadRequestException, forwardRef, Inject, Injectable } from '@nestjs/common';
import { Permission } from "@/modules/permission/entities/permission.entity";
import { InjectRepository } from '@nestjs/typeorm';
import { Not, Repository } from 'typeorm';
import { SharedService } from '@/shared/shared.service';
import { Role } from '@/modules/role/entities/role.entity';
import { RedisService } from '@/shared/redis.service';
import { UserService } from '@/modules/user/user.service';
import { PermissionDto } from "@/modules/permission/dto/dto";

@Injectable()
export class PermissionService {
  constructor(
    @InjectRepository(Permission)
    private readonly permissionRep: Repository<Permission>,
    @InjectRepository(Role)
    private readonly roleRepo: Repository<Role>,
    private readonly sharedService: SharedService,
    private readonly redisService: RedisService,
    @Inject(forwardRef(() => UserService))
    private readonly userService: UserService,
  ) {}

  async createPermission(createPermissionDto: PermissionDto) {
    const { permissionCode, permissionName, parentId } = createPermissionDto;
    const isExist = await this.permissionRep.findOne({
      where: [{ permissionCode }, { permissionName }],
    });
    // console.log('isExist', isExist);
    if (isExist) throw new BadRequestException('权限编码或权限名称已存在');
    if (parentId) {
      const parentPermission = this.permissionRep.findOne({
        where: { id: parentId },
        select: ['id'],
      });
      if (!parentPermission) throw new BadRequestException('父级权限不存在');
    }
    const createPermission = this.permissionRep.create(createPermissionDto);
    const newPermission = await this.permissionRep.save(createPermission);
    return newPermission.id;
  }

  // 获取所有权限的树形结构
  async findAllTree() {
    const permissions = await this.permissionRep.find({
      order: { sort: 'DESC' },
    });
    return this.sharedService.handleTree(permissions);
  }

  // 获取系统所有api权限
  async findAllPermissions() {
    const permissionsApi = await this.permissionRep
      .createQueryBuilder('permission')
      .select('permission.permissionCode')
      .andWhere('permission.status = :status', { status: true })
      .getMany();
    return permissionsApi.map((item) => item.permissionCode);
  }

  // 修改权限
  async updatePermission(id: number, updatePermissionDto: PermissionDto) {
    // 判断是否存在相同的权限编码和权限名称
    const { permissionCode, permissionName } = updatePermissionDto;
    const permission = await this.permissionRep.findOne({
      where: [
        { permissionCode, id: Not(id) },
        { permissionName, id: Not(id) },
      ],
      select: ['permissionCode', 'permissionName'],
    });
    if (permission) {
      if (permission.permissionCode === permissionCode)
        throw new BadRequestException('权限编码已存在');
      if (permission.permissionName === permissionName)
        throw new BadRequestException('权限名称已存在');
    }
    // 判断父级权限是否存在,并且不能是自己
    if (updatePermissionDto.parentId) {
      const parentPermission = await this.permissionRep.findOne({
        where: { id: updatePermissionDto.parentId },
        select: ['id'],
      });
      if (!parentPermission) throw new BadRequestException('父级权限不存在');
      if (parentPermission.id === id) throw new BadRequestException('父级权限不能是自己');
    }
    await this.permissionRep.update(id, updatePermissionDto);
    // 刷新系统权限
    const permissions = await this.findAllPermissions(); // 获取出有API类型的标识，并且是启用状态的权限
    await this.redisService.set('SYSTEM_PERMISSIONS', JSON.stringify(permissions)); // 将系统所有的API权限缓存到redis中
    await this.userService.refreshAllOnlineUserPermission();
    return true;
  }

  // 删除权限
  async deletePermission(id: number) {
    const permission = await this.permissionRep.findOne({
      where: { id },
      relations: {
        roles: true,
      },
    });
    if (!permission) throw new BadRequestException('权限不存在或者已删除');
    if (permission.roles.length > 0) {
      throw new BadRequestException('该权限下存在角色，无法删除');
    }
    await this.permissionRep.delete(id);
    return true;
  }

  // 根据角色编码获取权限
  async getPermissionIdsByRoleCode(roleCode: string) {
    console.log('roleCode', roleCode);
    // 根据角色获取出所有的权限
    const role = await this.roleRepo
      .createQueryBuilder('role')
      .where('role.roleCode = :roleCode', { roleCode })
      .leftJoin('role.permissions', 'permission')
      .select(['role.id', 'permission.permissionCode']) // 选择 role.id 和 permission.permissionCode
      .getOne();
    return role?.permissions.map((item) => item.permissionCode) || [];
  }

  // 校验当前路由是否存在于menu资源
  async validateMenuPath(path: string) {
    const findMenu = await this.permissionRep
      .createQueryBuilder('permission')
      .where('permission.path = :path', { path })
      .andWhere('permission.type IN (:...type)', { type: ['MENU', 'ROUTE'] })
      .andWhere('permission.status = :status', { status: true })
      .select('permission.id')
      .getOne();
    return !!findMenu;
  }
}
